package com.hardware.dll;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;

/**
 * 爱迪尔门锁  MainDll.dll
 * 适用门锁系统：V6.51及以上版本。
 *
 * @作者 韩宗森
 * @创建时间 2024年10月24日 19:14
 */
public interface AidierDLL extends StdCallLibrary {

    // MainDll.dll 文件路径
    String path = System.getProperty("user.dir") + "\\aidier_dll_a\\MainDll";

    // 加载 dll 文件
    AidierDLL INSTANCE = (AidierDLL) Native.loadLibrary(path, AidierDLL.class);

// 一、门锁函数（必须已经安装并设置好门锁系统）----------------------------------------------------------

    /**
     * 1. 初始化函数
     *
     * @param software  指定门锁系统
     * @param server    指定门锁系统数据库安装的服务器（SQL Server）名。
     * @param username  用户名，用于门锁系统记录操作人员。
     * @param port      串口号，1-COM1，2-COM2，3-COM3，4-COM4依次类推。
     * @param Encoder   发行机类型，0-手动发行机，1-自动发行机，2-MSR206（磁卡）。
     * @param TMEncoder TM发行机类型，1-DS9097E，5-DS9097U
     * @return
     */
    int Init(int software, byte[] server, byte[] username, int port, int Encoder, int TMEncoder);

    /**
     * 2. 结束工作期
     *
     * @return
     */
    int EndSession();

    /**
     * 3. 更改操作员
     *
     * @param username 用户名，用于门锁系统记录操作人员
     */
    void ChangeUser(byte[] username);

    /**
     * 4. 发行新客人卡，此功能注销当前在用的客人卡，新发行的客人卡开门后原来的客人卡将不能使用
     *
     * @param room      房号，6字节字符串，必须是门锁系统设置的房号
     * @param gate      公共通道，字符串参数，“00”表示按默认授权通道，“99”表示授权所有公共通道，其他为指定通道代码。例如：“010203”表示授权01、02、03三个通道。
     * @param stime     起止时间，24字节字符串，格式yyyymmddhhnnyyyymmddhhnn，例如：“200012311230200101011230”表示2000年12月31日12时30分到2001年1月1日12时30分。Lock9200：起止时间不能在同一天内，且不能超过1个月。
     * @param guestname 客人姓名，最大30字节，可以为NULL。
     * @param guestid   客人ID，最大30字节，可以为NULL。
     * @param overflag  整形，是否覆盖当前卡上的内容。1-覆盖，当前卡不是新卡则自动注销（必须是客人卡）。0-不覆盖，不是新卡则返回。磁卡（手动发行机）忽略此参数，直接覆盖，不自动注销。
     * @param cardno    长整形指针，接收卡号（发卡后分配的唯一卡代码）。可以为NULL。
     * @param track1    字符串指针，磁卡第1轨数据，如不写此轨可为NULL。
     * @param track2    字符串指针，磁卡第2轨数据，如不写此轨可为NULL。
     * @return
     */
    int NewKey(byte[] room, byte[] gate, byte[] stime, byte[] guestname, byte[] guestid, int overflag, long cardno, byte[] track1, byte[] track2);

    /**
     * 5. “复制”客人卡，新发行的客人卡与原来的客人卡可同时使用，且起始时间相同。
     *
     * @param room      房号，6字节字符串，必须是门锁系统设置的房号。
     * @param gate      公共通道，字符串参数，“00”表示按默认授权通道，“99”表示授权所有公共通道，其他为指定通道代码。例如：“010203”表示授权01、02、03三个通道。
     * @param stime     起止时间，24字节字符串，格式yyyymmddhhnnyyyymmddhhnn，例如：“200012311230200101011230”表示2000年12月31日12时30分到2001年1月1日12时30分。起始时间与在用客人卡相同。
     * @param guestname 客人姓名，最大30字节，可以为NULL。
     * @param guestid   客人ID，最大30字节，可以为NULL。
     * @param overflag  整形，是否覆盖当前卡上的内容。1-覆盖，当前卡不是新卡则自动注销（必须是客人卡）。0-不覆盖，不是新卡则返回。磁卡（手动发行机）忽略此参数，直接覆盖，不自动注销。
     * @param cardno    长整形指针，接收卡号（发卡后分配的唯一卡代码）。可以为NULL。
     * @param track1    字符串指针，磁卡第1轨数据，如不写此轨可为NULL。
     * @param track2    字符串指针，磁卡第2轨数据，如不写此轨可为NULL。
     * @return
     */
    int DupKey(byte[] room, byte[] gate, byte[] stime, byte[] guestname, byte[] guestid, int overflag, long cardno, byte[] track1, byte[] track2);

    /**
     * 6. 读卡。
     *
     * @param room      字符串指针，接收返回的房号，建议10字节。
     * @param gate      字符串指针，接收返回的授权公共通道，可以为NULL。
     * @param stime     起止时间，24字节字符串，格式yyyymmddhhnnyyyymmddhhnn，例如：“200012311230200101011230”表示2000年12月31日12时30分到2001年1月1日12时30分。起始时间与在用客人卡相同。
     * @param guestname 字符串指针，接收返回的客人姓名，可以为NULL。
     * @param guestid   字符串指针，接收返回的客人ID，可以为NULL。
     * @param track1    接收磁卡第1轨数据，可以为NULL。
     * @param track2    接收磁卡第2轨数据,可以为NULL。
     * @param cardno    长整形指针，接收返回的卡号，可以为NULL。
     * @param st        整形指针，接收返回的卡状态，1-正常使用，3-正常注销，4-遗失注销，5-损毁注销，6-自动注销。可以为NULL。
     * @return
     */
    int ReadCard(byte[] room, byte[] gate, byte[] stime, byte[] guestname, byte[] guestid, byte[] track1, byte[] track2, long cardno, int st);
    int ReadCard(byte[] room, byte[] gate, byte[] stime, byte[] guestname, byte[] guestid, byte[] track1, byte[] track2, int cardno, int st);

    int ReadCard(char[] room, char[] gate, char[] stime, char[] gname, char[] gid,char[] unused1, char[] unused2, int[] cardno, int[] status);

    int ReadCard(Pointer room, Pointer gate, Pointer stime, Pointer gname, Pointer gid,
                 Pointer unused1, Pointer unused2, IntByReference cardno, IntByReference status);
    int ReadCard(PointerByReference room, PointerByReference gate, PointerByReference stime,
                 PointerByReference gname, PointerByReference gid, PointerByReference unused1,
                 PointerByReference unused2, IntByReference cardno, IntByReference status);

    int ReadCard(String room, String gate, String stime, String guestname, String guestid, String track1, String track2, long cardno, int st);
    int ReadCard(String room, String gate, String stime, String guestname, String guestid, String track1, String track2, String cardno, String st);

    int ReadCard(String room, String gate, String stime, String guestname, String guestid, String track1, String track2, String cardno);
    int ReadCard(String room, String gate, String stime, String guestname, String guestid, String track1, String track2, long cardno);

    int ReadCard(String room, String gate, String stime, String guestname, String guestid, String track1, String track2);
    int ReadCard(String room, String gate, String stime, String guestname, String guestid, String track1);
    int ReadCard(String room, String gate, String stime, String guestname, String guestid);
    int ReadCard(String room, String gate, String stime, String guestname);
    int ReadCard(String room, String gate, String stime);
    int ReadCard(String room, String gate);
    int ReadCard(String room);
    int ReadCard(long room);
    int ReadCard();

    /**
     * 7. 注销卡，同时更新数据库数据。
     *
     * @param cardno 卡号，可以为0。当此参数为0时：IC卡、RF卡、TM卡、磁卡（自动发行机）自动读取卡号并注销，同时更新数据库；磁卡（手动发行机）注销当前卡，不更新数据库，建议再调用CheckOut函数更新数据库，或先读卡获取卡号后再调用EraseCard。
     * @param track1 字符串指针，磁卡第1轨数据，如不写此轨可为NULL。
     * @param track2 字符串指针，磁卡第2轨数据，如不写此轨可为NULL。
     * @return
     */
    int EraseCard(long cardno, byte[] track1, byte[] track2);

    /**
     * 8. 退房，仅更新数据库数据，不注销卡。
     *
     * @param room   房号。
     * @param cardno 卡号，可以为0。当此参数为0时，将客房所有客人卡标记为正常注销。
     * @return
     */
    int CheckOut(byte[] room, long cardno);

    /**
     * 9. 遗失注销，仅更新数据库数据，不注销卡。
     *
     * @param room   房号。
     * @param cardno 卡号，标记为遗失注销客人卡的卡号。
     * @return
     */
    int Lostcard(byte[] room, long cardno);

// 二、公用函数（门锁接口和独立使用均可）-----------------------------------------------------------------

    /**
     * 10. 弹出卡。
     *
     * @return 见注1，独立使用时返回20表示‘没有调用SetPort’。
     */
    int PopCard();

    /**
     * 11. 设置串口，调用Init函数后不必调用此函数。
     *
     * @param software  指定门锁系统，参见注2。
     * @param port      串口号，整形，1-COM1，2-COM2，3-COM3，4-COM4依次类推。
     * @param encoder   发行机类型：0-手动发行机，1-自动发行机。
     * @param tmencoder TM发行机类型：1-DS9097E，5-DS9097U。
     * @return
     */
    int SetPort(int software, int port, int encoder, int tmencoder);

    /**
     * 12. 读Mifare卡ID，函数原形：
     *
     * @param pid 4字节无符指针，接收卡ID。
     * @return
     */
    int ReadCardId(long pid);

    /**
     * 13. 核对4442卡密码。
     *
     * @param sc IC卡密码，3字节无符字符指针。
     * @return
     */
    int CheckSC(byte[] sc);

    /**
     * 14. 读4442/14512卡数据
     *
     * @param start 起始地址，指定数据写的位置。对于Mifare卡（Adel9200），起始地址由两字节组成：高字节为块号，低字节为区号。如0x0102表示读取2区1块。
     * @param len   要读取数据的长度。对于Mifare卡（Adel9200）长度为16的整数倍。
     * @param str   无符字符指针，接收所读取的数据。对于Mifare卡（Adel9200）同时作为输入参数传入所读区的授权密码，由7个字节组成：第一个字节为授权码：若为0需核对A密码，若为1需核对B密码，后6个字节为密码。
     * @return
     */
    int ReadIC(int start, int len, byte[] str);

    /**
     * 15. 写数据到4442/14512卡（Lock3200K：建议用户使用0x80以后的存储区）。
     *
     * @param start 起始地址，指定数据写的位置；对于Mifare卡（Adel9200），起始地址由两字节组成：高字节为块号，低字节为区号。如0x0102表示读取2区1块。
     * @param len   写入数据的长度。对于Mifare卡（Adel9200）长度为16的整数倍。
     * @param str   无符字符指针，要写入IC卡的数据。对于Mifare卡（Adel9200）前7个字节传入所读区的授权密码：第一个字节为授权码：若为0需核对A密码，若为1需核对B密码，后6个字节为密码。从第8个字节开始为写入的数据。
     * @return
     */
    int WriteIC(int start, int len, byte[] str);

    /**
     * 16. 写磁卡，建议用户数据存储在1、2轨，门锁系统使用第3轨。
     *
     * @param track1 字符串指针，磁卡第1轨数据，如不写此轨可为NULL。
     * @param track2 字符串指针，磁卡第2轨数据，如不写此轨可为NULL。
     * @param track3 字符串指针，磁卡第3轨数据，如不写此轨可为NULL。
     * @return
     */
    int WriteMagCard(byte[] track1, byte[] track2, byte[] track3);

    /**
     * 17. 读磁卡
     *
     * @param track1 字符串指针，接收磁卡第1轨数据，如不读此轨为NULL。
     * @param track2 字符串指针，接收磁卡第2轨数据，如不读此轨为NULL。
     * @param track3 字符串指针，接收磁卡第3轨数据，如不读此轨为NULL。
     * @return
     */
    int ReadMagCard(byte[] track1, byte[] track2, byte[] track3);

    /**
     * 18. 读磁卡。
     *
     * @param Sound 指定声音和LED状态。11-绿灯1秒，长叫一声；12-红灯1秒，长叫一声；15-红灯1秒，短叫两声；16-短叫一声。
     * @return
     */
    int Reader_Beep(int Sound);

// 三、网络节电开关函数--------------------------------------------------------------------------------------

    /**
     * 19.
     *
     * @param buff     无符字符指针，卡上数据。
     * @param len      数据长度（字节）。
     * @param cardtype  整型指针，接收卡型：1-总裁卡，2-别墅卡，3-管理卡，4-总控卡，5-时钟卡，6-领班卡，7-楼层卡，8-清洁卡，9-客人卡，10-终止卡，11-会议卡，12-应急卡，13-退房卡，14-备用卡；可以为NULL。
     * @param cardst    整型指针，接收卡状态：1-正常，3-注销，4-遗失，5-损毁，6-过期；可以为NULL。
     * @param cardno    整型指针，接收卡号，可以为NULL。
     * @param roomno    字符指针，接收客人卡/备用卡房号，领班卡/楼层卡/清洁卡区域。不小于20字节，可以为NULL。
     * @param username  字符指针，接收客人姓名，不小于20字节，可以为NULL。
     * @param stime     字符指针，接收客人卡/清洁卡有效期，不小于28字节，可以为NULL。格式yyyymmddhhnnyyyymmddhhnn，例如：“200012311230200101011230”表示2000年12月31日12时30分到2001年1月1日12时30分。
     * @return
     */
    int GetBuffInfo(byte[] buff, int len, int cardtype, int cardst, int cardno, byte[] roomno, byte[] username, byte[] stime);

    /**
     *
     * @param cardno    卡号。
     * @param cardtype  卡型。
     * @param cardst    整型指针，接收卡状态：1-正常，3-注销，4-遗失，5-损毁，6-过期；可以为NULL。
     * @param roomno    字符指针，接收客人卡/备用卡房号，领班卡/楼层卡/清洁卡区域。不小于20字节，可以为NULL。
     * @param username  字符指针，接收客人姓名，不小于20字节，可以为NULL。
     * @param stime     字符指针，接收客人卡/清洁卡有效期，不小于28字节，可以为NULL。
     *                  格式yyyymmddhhnnyyyymmddhhnn，例如：“200012311230200101011230”表示2000年12月31日12时30分到2001年1月1日12时30分。
     * @return
     */
    int GetCardInfo(int cardno, int cardtype, int cardst, byte[] roomno, byte[] username, byte[] stime);

    /*
    注：一、函数返回值：
    0-操作成功                       1-读写错误/数据错误
    2-卡已损坏                       3-无卡
    4-串口错误                       5-卡被更换
    6-不是新卡                       7-卡是新卡
    8-非本系统卡                     9-不是客人卡
    10-不是会员卡                    11-密码错误
    12-无开门记录                    13-卡型不正确
    14-参数错误                      15-用户取消操作(按下<ESC>键)
    16-等待超时                      17-插卡错误
    18-卡是空白卡或插卡错误          19-保留(为向前兼容)
    20-没有调用Init函数             21-不支持该版本的门锁软件
    22-连接(门锁系统数据库)错误      23-门锁系统参数不存在
    24-初始化失败                    25-没有客人在住/指定客人不存在
    26-客房已满                      27-没有此卡记录
    28-没有调用SetPort函数          29-无效的客房房号
    30-错误的时间范围                31-卡号已存在，无法登记（Lock9200）
    32-不支持调用                    33-无效的授权码，授权码错误或过期

    二、门锁系统常量：
        Lock3200-1    Lock3200K-2    Lock4200-3    Lock4200D-4    Lock5200-5
        Lock6200-6    Lock7200-7     Lock7200D-8   Lock9200-9     Lock9200T-10

        A30-11   A50-14	A90-18   A92-22


    三、运行环境：32位Windows操作系统，使用门锁函数需安装MDAC。

    四、调用方式：遵循Windows API调用标准，即stdcall。

    五、参数说明：[in]为输入参数，[out]为输出参数。

     */
}
